package com.csii.modules.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.csii.core.constant.CacheConstant;
import com.csii.core.constant.CommonConstant;
import com.csii.core.constant.DataBaseConstant;
import com.csii.core.constant.WebsocketConst;
import com.csii.core.exception.AppException;
import com.csii.core.system.vo.*;
import com.csii.core.util.*;
import com.csii.galaxy.studio.entity.SysDict;
import com.csii.galaxy.studio.enums.MessageCategory;
import com.csii.modules.message.entity.SysMessage;
import com.csii.modules.message.entity.SysMessageTemplate;
import com.csii.modules.message.handle.enums.SendMsgStatusEnum;
import com.csii.modules.message.service.ISysMessageService;
import com.csii.modules.message.service.ISysMessageTemplateService;
import com.csii.modules.message.websocket.WebSocket;
import com.csii.modules.system.entity.*;
import com.csii.modules.system.mapper.SysAnnouncementMapper;
import com.csii.modules.system.mapper.SysAnnouncementSendMapper;
import com.csii.modules.system.mapper.SysCategoryMapper;
import com.csii.modules.system.mapper.SysLogMapper;
import com.csii.modules.system.service.ISysBaseAPI;
import com.csii.modules.system.service.ISysDataSourceService;
import com.csii.modules.system.service.ISysDictService;
import com.csii.user.entity.SysUser;
import com.csii.user.service.ISysUserBaseService;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;

/**
 * @Description: 底层共通业务API，提供其他独立模块调用
 * @Author: scott
 * @Date:2019-4-20
 * @Version:V1.0
 */
@Slf4j
@Service
public class SysBaseApiImpl implements ISysBaseAPI {
	/** 当前系统数据库类型 */
	private static String DB_TYPE = "";
	@Autowired
	private ISysMessageTemplateService sysMessageTemplateService;
	@Resource
	private SysLogMapper sysLogMapper;
	@Autowired
	private ISysDictService sysDictService;
	@Resource
	private SysAnnouncementMapper sysAnnouncementMapper;
	@Resource
	private SysAnnouncementSendMapper sysAnnouncementSendMapper;
	@Resource
    private WebSocket webSocket;
	@Resource
	private SysCategoryMapper categoryMapper;

	@Autowired
	private ISysDataSourceService dataSourceService;
	@Autowired
	private ISysUserBaseService userService;
	@Autowired
	private ISysMessageService sysMessageService;

	@Override
	public void addLog(String LogContent, Integer logType, Integer operatetype) {
		SysLog sysLog = new SysLog();
		//注解上的描述,操作日志内容
		sysLog.setLogContent(LogContent);
		sysLog.setLogType(logType);
		sysLog.setOperateType(operatetype);

		//请求的方法名
		//请求的参数

		try {
			//获取request
			HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
			//设置IP地址
			sysLog.setIp(IPUtils.getIpAddr(request));
		} catch (Exception e) {
			sysLog.setIp("127.0.0.1");
		}

		//获取登录用户信息
		LoginUser sysUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if(sysUser!=null){
			sysLog.setUserid(sysUser.getUsername());
			sysLog.setUsername(sysUser.getRealname());

		}
		sysLog.setCreateTime(new Date());
		//保存系统日志
		sysLogMapper.insert(sysLog);
	}



	@Override
	public String getDatabaseType() throws SQLException {
		if(oConvertUtils.isNotEmpty(DB_TYPE)){
			return DB_TYPE;
		}
		DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
		return getDatabaseTypeByDataSource(dataSource);
	}

	@Override
	@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "T(com.csii.core.util.TenantContext).getTenantDefaultString()+#code")
	public List<DictModel> queryDictItemsByCode(String code) {
		return sysDictService.queryDictItemsByCode(code);
	}

	@Override
	public List<DictModel> queryTableDictItemsByCode(String table, String text, String code) {
		return sysDictService.queryTableDictItemsByCode(table, text, code);
	}

	@Override
	public List<DictModel> queryAllDepartBackDictModel() {
		return sysDictService.queryAllDepartBackDictModel();
	}


	@Override
	public void updateSysAnnounReadFlag(String busType, String busId) {
		SysAnnouncement announcement = sysAnnouncementMapper.selectOne(new QueryWrapper<SysAnnouncement>().eq("bus_type",busType).eq("bus_id",busId));
		if(announcement != null){
			LoginUser sysUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			String userId = sysUser.getId();
			LambdaUpdateWrapper<SysAnnouncementSend> updateWrapper = new UpdateWrapper().lambda();
			updateWrapper.set(SysAnnouncementSend::getReadFlag, CommonConstant.HAS_READ_FLAG);
			updateWrapper.set(SysAnnouncementSend::getReadTime, new Date());
			updateWrapper.last("where annt_id ='"+announcement.getId()+"' and user_id ='"+userId+"'");
			SysAnnouncementSend announcementSend = new SysAnnouncementSend();
			sysAnnouncementSendMapper.update(announcementSend, updateWrapper);
		}
	}

	@Override
    public String parseTemplateByCode(String templateCode, Map<String, String> map) {
        List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
        if(sysSmsTemplates==null||sysSmsTemplates.size()==0){
            throw new AppException("消息模板不存在，模板编码："+templateCode);
        }
        SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
        //模板内容
        String content = sysSmsTemplate.getTemplateContent();
        if(map!=null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String str = "${" + entry.getKey() + "}";
                content = content.replace(str, entry.getValue());
            }
        }
        return content;
    }


	@Override
	public void sendSysAnnouncement(String fromUser, String toUser, String title, String msgContent) {
		this.sendSysAnnouncement(fromUser, toUser, title, msgContent, MessageCategory.MSG_CATEGORY_SYS.getCode());
	}
	@Override
	public void sendSysAnnouncement(String fromUser, String toUser, String title, String msgContent,String msgCategory) {
		SysAnnouncement announcement = new SysAnnouncement();
		announcement.setTitle(title);
		announcement.setMsgContent(msgContent);
		announcement.setSender(fromUser);
		announcement.setPriority(CommonConstant.PRIORITY_M);
		announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
		announcement.setSendStatus(CommonConstant.HAS_SEND);
		announcement.setSendTime(new Date());
		announcement.setMsgCategory(msgCategory);
		announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
		sendMessage(toUser,announcement);
	}


	@Override
	public void sendSysAnnouncement(String fromUser, String toUser, String title, Map<String, String> map, String templateCode){
		sendSysAnnouncement(fromUser,  toUser,  title, map, templateCode, MessageCategory.MSG_CATEGORY_SYS.getCode());
	}
	@Override
	public void sendSysAnnouncement(String fromUser, String toUser, String title, Map<String, String> map, String templateCode,String msgCategory){
		sendSysAnnouncement(fromUser,  toUser,  title, map, templateCode,msgCategory
				,false);
	}
	@Override
	public void sendSysAnnouncement(String fromUser, String toUser, String title, Map<String, String> map, String templateCode,String msgCategory,Boolean callMe) {
		List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
        if(sysSmsTemplates==null||sysSmsTemplates.size()==0){
            throw new AppException("消息模板不存在，模板编码："+templateCode);
        }
		SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
        //更新测试参数
        if(map!=null&&map.size()>0) {
			sysSmsTemplate.setTemplateTestJson(JSONObject.toJSONString(map));
			sysMessageTemplateService.updateById(sysSmsTemplate);
		}
		//模板标题
		title = title==null?sysSmsTemplate.getTemplateName():title;
		//模板内容
		String content = Optional.ofNullable(sysSmsTemplate.getTemplateContent()).orElse("");
		String subTitle = Optional.ofNullable(sysSmsTemplate.getSubTitle()).orElse("");
		String goUrl= Optional.ofNullable(sysSmsTemplate.getGoUrl()).orElse("");
		if(map!=null) {
			for (Map.Entry<String, String> entry : map.entrySet()) {
				String str = "${" + entry.getKey() + "}";
				title = title.replace(str, entry.getValue());
				if(content != null){
					content = content.replace(str, entry.getValue());
				}
				subTitle= subTitle.replace(str, entry.getValue());
				goUrl= goUrl.replace(str, entry.getValue());
			}
		}
		if(!sysSmsTemplate.getTemplateType().equals("4")){
			SysMessage sysMessage =new SysMessage();
			sysMessage.setEsType(sysSmsTemplate.getTemplateType());
			sysMessage.setEsReceiver(toUser);
			sysMessage.setEsTitle(title);
			sysMessage.setEsContent(content);
			sysMessage.setEsParam(JSONObject.toJSONString(map));
			sysMessage.setEsSendTime(new Date());
			sysMessage.setEsSendStatus(SendMsgStatusEnum.WAIT.getCode());
			sysMessage.setEsSendNum(0);
			if (sysMessageService.save(sysMessage)) {
				return;
			}
		}
		SysAnnouncement announcement = new SysAnnouncement();
		announcement.setTitle(title);
		announcement.setMsgContent(content);
		announcement.setSender(fromUser);
		announcement.setPriority(CommonConstant.PRIORITY_M);
		announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
		announcement.setSendStatus(CommonConstant.HAS_SEND);
		announcement.setSendTime(new Date());
		announcement.setMsgCategory(msgCategory);
		announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
		announcement.setMainButton(sysSmsTemplate.getMainButton());
		announcement.setOpenPage(goUrl);
		announcement.setMsgAbstract(subTitle);
		announcement.setOpenType(sysSmsTemplate.getOpenType());
		announcement.setCallMe(callMe==null?false:callMe);
		sendMessage(toUser,announcement);
	}

	/**
	 * 工作流发送消息
	 * @param actBusId 流程业务id
	 * @param fromUser 发送人(用户登录账户)
	 * @param toUser  发送给(用户登录账户)
	 * @param title  消息主题
	 * @param msgContent  消息内容
	 */
	@Override
	@Deprecated
	public void sendSysAnnouncementAct(String actBusId,String fromUser, String toUser, String title, String msgContent) {
		SysAnnouncement announcement = new SysAnnouncement();
		announcement.setTitle(title);
		announcement.setMsgContent(msgContent);
		announcement.setSender(fromUser);
		announcement.setPriority(CommonConstant.PRIORITY_M);
		announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
		announcement.setSendStatus(CommonConstant.HAS_SEND);
		announcement.setSendTime(new Date());
		announcement.setMsgCategory(MessageCategory.MSG_CATEGORY_SYS.getCode());
		announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
		sendMessage(toUser,announcement);
	}
	private void sendMessage(String toUser,SysAnnouncement announcement){
		sysAnnouncementMapper.insert(announcement);
		// 2.插入用户通告阅读标记表记录
		String userId = toUser;
		String[] userIds = userId.split(",");
		String anntId = announcement.getId();
		for(int i=0;i<userIds.length;i++) {
			if(oConvertUtils.isNotEmpty(userIds[i])) {
				SysUser sysUser = userService.getUserByName(userIds[i]);
				if(sysUser==null) {
					continue;
				}
				SysAnnouncementSend announcementSend = new SysAnnouncementSend();
				announcementSend.setAnntId(anntId);
				announcementSend.setUserId(sysUser.getId());
				announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
				sysAnnouncementSendMapper.insert(announcementSend);
				JSONObject obj = new JSONObject();
				obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
				obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
				obj.put(WebsocketConst.MSG_ID, announcement.getId());
				obj.put(WebsocketConst.MSG_TXT, announcement.getTitle());
				webSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
			}
		}
	}

	/**
	 * 获取数据库类型
	 * @param dataSource
	 * @return
	 * @throws SQLException
	 */
	private String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException{
		if("".equals(DB_TYPE)) {
			Connection connection = dataSource.getConnection();
			try {
				DatabaseMetaData md = connection.getMetaData();
				String dbType = md.getDatabaseProductName().toLowerCase();
				if(dbType.indexOf("mysql")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;
				}else if(dbType.indexOf("oracle")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
				}else if(dbType.indexOf("sqlserver")>=0||dbType.indexOf("sql server")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
				}else if(dbType.indexOf("postgresql")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
				}else {
					throw new AppException("数据库类型:["+dbType+"]不识别!");
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}finally {
				connection.close();
			}
		}
		return DB_TYPE;

	}

	@Override
	public List<DictModel> queryAllDict() {
		// 查询并排序
		QueryWrapper<SysDict> queryWrapper = new QueryWrapper<SysDict>();
		queryWrapper.orderByAsc("create_time");
		List<SysDict> dicts = sysDictService.list(queryWrapper);
		// 封装成 model
		List<DictModel> list = new ArrayList<DictModel>();
		for (SysDict dict : dicts) {
			list.add(new DictModel(dict.getDictCode(), dict.getDictName()));
		}

		return list;
	}

	@Override
	public List<SysCategoryModel> queryAllDSysCategory() {
		List<SysCategory> ls = categoryMapper.selectList(null);
		List<SysCategoryModel> res = oConvertUtils.entityListToModelList(ls,SysCategoryModel.class);
		return res;
	}

	@Override
	public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql) {
		return sysDictService.queryTableDictItemsByCodeAndFilter(table,text,code,filterSql);
	}

	@Override
	public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray) {
		return sysDictService.queryTableDictByKeys(table,text,code,Joiner.on(",").join(keyArray));
	}

	@Override
	public List<ComboModel> queryAllUser() {
		List<ComboModel> list = new ArrayList<ComboModel>();
		List<SysUser> userList = userService.selectAllList();
		for(SysUser user : userList){
			ComboModel model = new ComboModel();
			model.setTitle(user.getRealname());
			model.setId(user.getId());
			model.setUsername(user.getUsername());
			list.add(model);
		}
		return list;
	}


	@Override
	public DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId) {
		SysDataSource dbSource = dataSourceService.getById(dbSourceId);
		return new DynamicDataSourceModel(dbSource);
	}

	@Override
	public DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode) {
		SysDataSource dbSource = dataSourceService.getOne(new LambdaQueryWrapper<SysDataSource>().eq(SysDataSource::getCode, dbSourceCode));
		return new DynamicDataSourceModel(dbSource);
	}


	@Override
	public void sendWebSocketMsg(String[] userIds, String cmd) {
		JSONObject obj = new JSONObject();
		obj.put(WebsocketConst.MSG_CMD, cmd);
		webSocket.sendMoreMessage(userIds, obj.toJSONString());
	}

	/**
	 * 推送签到人员信息
	 * @param userId
	 */
	@Override
	public void meetingSignWebsocket(String userId) {
		JSONObject obj = new JSONObject();
		obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_SIGN);
		obj.put(WebsocketConst.MSG_USER_ID,userId);
		//TODO 目前全部推送，后面修改
		webSocket.sendAllMessage(obj.toJSONString());
	}
}
